package com.itdct.onflow.generator.template

import com.itdct.onflow.generator.base.BaseTemplate
import com.itdct.onflow.generator.config.GeneratorConfig
import com.itdct.onflow.generator.constant.GroupEnum
import com.itdct.onflow.generator.model.ClassModel
import com.itdct.onflow.generator.model.CompareResultModel
import com.itdct.onflow.generator.model.FieldModel

/**
 * @author Zhouwx
 * @date 2025/8/13 13:45:13
 * @version 1.0
 * @description
 */
class ServiceTemplate(classModel: ClassModel, generatorConfig: GeneratorConfig) : BaseTemplate(classModel, generatorConfig) {
    override fun render(): String {
        return """
${uuidPrint()}
package ${classModel.packageName}.service

import com.itdct.onflow.core.extend.*
import com.itdct.onflow.core.vo.KeyLabelValueVo
import com.itdct.onflow.core.vo.RespPageVo
import com.itdct.onflow.core.vo.RespVo
import ${classModel.packageName}.entity.${classModel.className}Entity
import ${classModel.packageName}.mapper.${classModel.className}Mapper
import ${classModel.packageName}.qo.${classModel.className}EditQo
import ${classModel.packageName}.qo.${classModel.className}SearchQo
import ${classModel.packageName}.vo.${classModel.className}DetailVo
import ${classModel.packageName}.vo.${classModel.className}ListVo
import com.itdct.onflow.system.common.base.BaseSysService
import com.itdct.onflow.system.common.context.Context
import com.itdct.onflow.system.common.extend.dict
import com.itdct.onflow.core.constant.CommonString
import com.itdct.onflow.core.constant.ReturnCode
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

/**
 * @author ${generatorConfig.authorName}
 * @date ${getDateString()}
 * @version 1.0
 * @description ${classModel.classUsage}服务
 */
@Service
class ${classModel.className}Service(
    val ${classModel.classNameLowCamel}Mapper: ${classModel.className}Mapper
) : BaseSysService() {

    @Transactional(rollbackFor = [Exception::class])
    fun add(qo: ${classModel.className}EditQo, context: Context): RespVo<Long> {
        val addEntity = qo.toEntity(${classModel.className}Entity::class.java)
        val id = ${classModel.classNameLowCamel}Mapper.insertEx(addEntity)
        return success(id)
    }

    @Transactional(rollbackFor = [Exception::class])
    fun update(qo: ${classModel.className}EditQo, context: Context): RespVo<Unit> {
        val updateEntity = ${classModel.classNameLowCamel}Mapper.selectByIdEx(qo.id)
        qo.injectValue(updateEntity)
        ${classModel.classNameLowCamel}Mapper.updateEx(updateEntity)
        return success()
    }

    fun delete(qo: ${classModel.className}EditQo, context: Context): RespVo<Unit> {
        val ids = qo.ids ?: fail(ReturnCode.LACK_PARAM, CommonString.REQUIRE_DELETE_ID_LIST)
        val deleteEntities = ${classModel.classNameLowCamel}Mapper.selectByIdsEx(ids)
        ${classModel.classNameLowCamel}Mapper.deleteBatchEx(deleteEntities)
        return success()
    }

    fun detail(qo: ${classModel.className}SearchQo, context: Context): RespVo<${classModel.className}DetailVo> {
        val id = qo.id ?: fail(ReturnCode.LACK_PARAM, CommonString.REQUIRE_ID)
        val vo = ${classModel.classNameLowCamel}Mapper.findById(id) ?: fail(CommonString.ENTITY_NOT_FOUND_USAGE("${classModel.classUsage}", id))
        return success(vo.dict())
    }

    fun page(qo: ${classModel.className}SearchQo, context: Context): RespPageVo<${classModel.className}ListVo> {
        startPage(context)
        val pageData = ${classModel.classNameLowCamel}Mapper.findByList(qo)
        return successPage(pageData.dict())
    }
    
${rangeStart("selectFunctions")}
${selectListFunctions()}
${rangeEnd("selectFunctions")}
}
        """.trimIndent()
    }

    override fun onModify(compareResultModel: CompareResultModel, content: String): String {
        var content = content
        val addForSelectFields = compareResultModel.addForSelect
        val addIndex = content.indexOf(rangeEnd("selectFunctions"))
        content = insertFieldListContent(content, addForSelectFields, addIndex, { index, fieldModel -> selectListContent(fieldModel) })

        val delForSelect = compareResultModel.delForSelect
        content = deleteRangeFunctionCode(content, "selectFunctions", delForSelect, { fieldModel -> selectListContent(fieldModel) })
        return content
    }

    fun selectListFunctions(): String {
        return classModel.fieldList.filter {
            it.forSelect
        }.map {
            selectListContent(it)
        }.joinToString("\n")
    }

    private fun selectListContent(it: FieldModel) = """
    |
    |    fun select${it.nameBigCamel}List(qo: ${classModel.className}SearchQo, context: Context): RespVo<List<KeyLabelValueVo>> {
    |        val vos = ${classModel.classNameLowCamel}Mapper.select${it.nameBigCamel}List(qo)
    |        return success(vos)
    |    }
                """.trimMargin()

    override fun belongGroup(): GroupEnum {
        return GroupEnum.BACKEND
    }

    override fun subModuleName(): String {
        return "service"
    }

    override fun getFolderFileName(): String {
        return "service/${classModel.className}Service.kt"
    }
}